// 6.4 函数重载
/**
 *
 */
#include <iostream>
#include <initializer_list>
#include <iterator>
#include <vector>
using std::begin, std::end;
using std::cin, std::cout, std::endl;
using std::initializer_list;
using std::string;
using std::vector;

// 不允许两个函数除了返回类型外其他所有的要素都相同。
string lookup(const int &);
// int lookup(const int&); // 错误，与上个函数相比只有返回类型不通

// 判断两个形参的类型是否相异
string look(const int &a);
string look(const int &);
string look(const int &b); // 这三个是同一个函数声明

// 重载和const形参
// 一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开来
int up(int);
int up(const int); // 重复声明了 int up(int);
int lp(int *);
int lp(int *const); // 重复声明了 int lp(int*);
// 如果形参是某种类型的指针或引用，则通过区分其指向的是常量对象还是非常量对象可以实现函数重载，此时的const是底层的
int abc(int&);       // 函数作用于int的引用
int abc(const int&); // 新函数，作用于常量引用
int abc(int*);       // 新函数，作用于指向int的指针
int abc(const int*); // 新函数，作用于指向常量的指针

// const_cast和重载
// 在4.11.3节（第145页）中我们说过，const_cast在重载函数的情景中最有用。
const string &shorterString(const string &s1,const string &s2)
{
    return (s1.size() > s2.size()) ? s2 : s1;
}
string &shorterString(string &s1,string &s2)
{
    // 在这个版本的函数中，首先将它的实参强制转换成对const的引用，然后调用了shorterString函数的const版本。
    // const版本返回对const string的引用，这个引用事实上绑定在了某个初始的非常量实参上。
    // 因此，我们可以再将其转换回一个普通的string&，这显然是安全的。
    auto &r = shorterString(const_cast<const string&>(s1),const_cast<const string&>(s2));
    return const_cast<string&>(r);
}

// 如果我们在内层作用域中声明名字，它将隐藏外层作用域中声明的同名实体。在不同的作用域中无法重载函数名
void print(const string&);
void print(double); // 重载print函数

int main(int argc, char const *argv[])
{
    // 在局部作用域中声明函数不是一个好习惯
    void print(int); // 新作用域，隐藏了之前的print函数
    //print("123"); // 错误，print(const string&)被隐藏了
    print(123); // 正确，当前print(int)可见
    return 0;
}

// 定义print函数
void print(int i)
{
    cout << i << endl;
};
